Step 0: check and install needed packages. Load the libraries and functions.

This notebook was prepared with the following environmental settings.

print(R.version)
               _                           
platform       x86_64-apple-darwin13.4.0   
arch           x86_64                      
os             darwin13.4.0                
system         x86_64, darwin13.4.0        
status                                     
major          3                           
minor          3.2                         
year           2016                        
month          10                          
day            31                          
svn rev        71607                       
language       R                           
version.string R version 3.3.2 (2016-10-31)
nickname       Sincere Pumpkin Patch       

Overview of sentence length distribution by different types of speeches.

Nomination speeches

First, we look at nomination acceptance speeches at major party’s national conventions. For relevant to Trump’s speeches, we limit our attention to speeches for the first terms of former U.S. presidents. We noticed that a number of presidents have very short sentences in their nomination acceptance speeches.

First term

par(mar=c(4, 11, 2, 2))
#sel.comparison=levels(sentence.list$FileOrdered)
sentence.list.sel=filter(sentence.list, 
                        File == "DonaldJTrump")
sentence.list.sel$type=factor(sentence.list.sel$type)
sentence.list.sel$typeOrdered=reorder(sentence.list.sel$type, 
                                  sentence.list.sel$word.count, 
                                  mean, 
                                  order=T)
beeswarm(word.count~typeOrdered, 
         data=sentence.list.sel,
         horizontal = TRUE, 
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=0.5/nlevels(sentence.list.sel$typeOrdered),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Different speeches of DonaldJTrump")

sentence.list%>%
  filter(File=="DonaldJTrump", 
         type=="nomin", 
         word.count<=3)%>%
  select(sentences)%>%sample_n(10)
sentence.list%>%
  filter(File=="DonaldJTrump", 
         type=="inaug", 
         word.count<=3)%>%
  select(sentences)%>%sample_n(5)
sentence.list%>%
  filter(File=="DonaldJTrump", 
         type=="speeches", 
         word.count<=3)%>%
  select(sentences)%>%sample_n(10)

Second term

count_term <- table(speech.list[speech.list$type == "inaug",]$File)
multi.term.sel <- names(which(count_term > 1))
for(i in 1:length(multi.term.sel)){
  
  png(paste("../output/", multi.term.sel[i], "compare12.png", sep=""),
      width=300, height=300)
#sel.comparison=levels(sentence.list$FileOrdered)
sentence.list.sel=filter(sentence.list, 
                        type=="inaug", File%in%multi.term.sel[i])
sentence.list.sel$Term=factor(sentence.list.sel$Term)
sentence.list.sel$termOrdered=reorder(sentence.list.sel$Term, 
                                  sentence.list.sel$word.count, 
                                  mean, 
                                  order=T)
beeswarm(word.count~termOrdered, 
         data=sentence.list.sel,
         horizontal = TRUE, 
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=3/nlevels(sentence.list.sel$termOrdered),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Inauguration speeches of multi-term")
  dev.off()
  
  }

What are these short sentences?

sentence.list%>%
  filter(File=="DonaldJTrump", 
         type=="nomin", 
         word.count<=3)%>%
  select(sentences)%>%sample_n(10)
sentence.list%>%
  filter(File=="AlbertGore,Jr", 
         type=="nomin", 
         word.count<=3)%>%
  select(sentences)%>%sample_n(10)
sentence.list%>%
  filter(File=="Clinton", 
         type=="nomin", 
         word.count<=3)%>%
  select(sentences)
sentence.list%>%
  filter(File=="WilliamJClinton", 
         type=="nomin", Term==1,
         word.count<=3)%>%
  select(sentences)

Inaugural speeches

We notice that the sentences in inaugural speeches are longer than those in nomination acceptance speeches.

sentence.list.sel=sentence.list%>%filter(type=="inaug", File%in%sel.comparison, Term==1)
sentence.list.sel$File=factor(sentence.list.sel$File)
sentence.list.sel$FileOrdered=reorder(sentence.list.sel$File, 
                                  sentence.list.sel$word.count, 
                                  mean, 
                                  order=T)
par(mar=c(4, 11, 2, 2))
beeswarm(word.count~FileOrdered, 
         data=sentence.list.sel,
         horizontal = TRUE,
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.sel$FileOrdered),
         las=2, ylab="", xlab="Number of words in a sentence.",
         main="Inaugural Speeches")

Short sentences in inaugural speeches.

sentence.list%>%
  filter(File=="BarackObama", 
         type=="inaug", 
         word.count<=3)%>%
  select(sentences)
trump_bigrams <- speech.list[speech.list$File == "DonaldJTrump",] %>%
  unnest_tokens(bigram, fulltext, token = "ngrams", n = 2)
bigrams_separated <- trump_bigrams %>%
  separate(bigram, c("word1", "word2"), sep = " ")
bigrams_filtered <- bigrams_separated %>%
  filter(!word1 %in% stop_words$word) %>%
  filter(!word2 %in% stop_words$word)
bigram_counts <- bigrams_filtered %>% 
  count(word1, word2, sort = TRUE)
bigrams_united <- bigrams_filtered %>%
  unite(bigram, word1, word2, sep = " ")
bigrams_united <- bigrams_united %>%
  count(type, bigram) %>%
  arrange(desc(n)) 
bigrams_united <- bigrams_united %>% 
  mutate(bigram = factor(bigram, levels = rev(unique(bigram)))) %>%
  group_by(type) %>% 
  arrange(desc(n))%>%
  top_n(5) %>% 
  ungroup
Selecting by n
ggplot(bigrams_united, aes(bigram, n, fill = type)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  labs(x = NULL, y = "count of words") +
  facet_wrap(~type, ncol = 2, scales = "free") +
  coord_flip()

##################

Step 5: Data analysis — sentiment analsis

Sentence length variation over the course of the speech, with emotions.

How our presidents (or candidates) alternate between long and short sentences and how they shift between different sentiments in their speeches. It is interesting to note that some presidential candidates’ speech are more colorful than others. Here we used the same color theme as in the movie “Inside Out.”

image

image

par(mfrow=c(4,1), mar=c(1,0,2,0), bty="n", xaxt="n", yaxt="n", font.main=1)
f.plotsent.len(In.list=sentence.list, InFile="HillaryClinton", 
               InType="nomin", InTerm=1, President="Hillary Clinton")
f.plotsent.len(In.list=sentence.list, InFile="DonaldJTrump", 
               InType="nomin", InTerm=1, President="Donald Trump")
f.plotsent.len(In.list=sentence.list, InFile="BarackObama", 
               InType="nomin", InTerm=1, President="Barack Obama")
f.plotsent.len(In.list=sentence.list, InFile="GeorgeWBush", 
               InType="nomin", InTerm=1, President="George W. Bush")

What are the emotionally charged sentences?

print("Hillary Clinton")
[1] "Hillary Clinton"
speech.df=tbl_df(sentence.list)%>%
  filter(File=="HillaryClinton", type=="nomin", word.count>=4)%>%
  select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "Some of you are frustrated, even furious."                        
[2] "It's a big deal."                                                 
[3] "Powerful forces are threatening to pull us apart."                
[4] "Powerful forces are threatening to pull us apart."                
[5] "It's a big deal."                                                 
[6] "My mother, Dorothy, was abandoned by her parents as a young girl."
[7] "It's a big deal."                                                 
[8] "Bonds of trust and respect are fraying."                          
print("Barack Obama")
[1] "Barack Obama"
speech.df=tbl_df(sentence.list)%>%
  filter(File=="BarackObama", type=="nomin", Term==1, word.count>=5)%>%
  select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "They could've heard words of anger and discord."
[2] "And that's to be expected."                     
[3] "It's not because John McCain doesn't care."     
[4] "Now let there be no doubt."                     
[5] "That promise is our greatest inheritance."      
[6] "Now let there be no doubt."                     
[7] "That's not the judgment we need."               
[8] "That promise is our greatest inheritance."      
print("George W Bush")
[1] "George W Bush"
speech.df=tbl_df(sentence.list)%>%
  filter(File=="GeorgeWBush", type=="nomin", Term==1, word.count>=4)%>%
  select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "On the other side of that wall are poverty and prison, addiction and despair."                                           
[2] "We're proud of you."                                                                                                     
[3] "But they've got it backwards."                                                                                           
[4] "And at the earliest possible date, my administration will deploy missile defenses to guard against attack and blackmail."
[5] "I appreciate his friendship."                                                                                            
[6] "On the other side of that wall are poverty and prison, addiction and despair."                                           
[7] "They had their chance."                                                                                                  
[8] "Corporations are responsible to treat their workers fairly and to leave the air and waters clean."                       
print("Donald Trump")
[1] "Donald Trump"
speech.df=tbl_df(sentence.list)%>%
  filter(File=="DonaldJTrump", type=="nomin", Term==1, word.count>=5)%>%
  select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "Once again, France is the victim of brutal Islamic terrorism."                                                   
[2] "God bless you, and good night!"                                                                                  
[3] "I have visited the laid-off factory workers, and the communities crushed by our horrible and unfair trade deals."
[4] "Once again, France is the victim of brutal Islamic terrorism."                                                   
[5] "God bless you, and good night!"                                                                                  
[6] "Three were killed, and three were very very badly injured."                                                      
[7] "God bless you, and good night!"                                                                                  
[8] "God bless you, and good night!"                                                                                  

Clustering of emotions

heatmap.2(cor(sentence.list%>%filter(type=="inaug")%>%select(anger:trust)), 
          scale = "none", 
          col = bluered(100), , margin=c(6, 6), key=F,
          trace = "none", density.info = "none")
par(mar=c(4, 6, 2, 1))

emo.means=colMeans(select(sentence.list, anger:trust)>0.01)
col.use=c("red2", "darkgoldenrod1", 
            "chartreuse3", "blueviolet",
            "darkgoldenrod2", "dodgerblue3", 
            "darkgoldenrod1", "darkgoldenrod1")
barplot(emo.means[order(emo.means)], las=2, col=col.use[order(emo.means)], horiz=T, main="Inaugural Speeches")

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKCiMgU3RlcCAwOiBjaGVjayBhbmQgaW5zdGFsbCBuZWVkZWQgcGFja2FnZXMuIExvYWQgdGhlIGxpYnJhcmllcyBhbmQgZnVuY3Rpb25zLiAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPSBGQUxTRX0Kc291cmNlKCIuLi9saWIvbGlicmFyeS5SIikKc291cmNlKCIuLi9saWIvdGV4dC1wcmVwLlIiKQpgYGAKVGhpcyBub3RlYm9vayB3YXMgcHJlcGFyZWQgd2l0aCB0aGUgZm9sbG93aW5nIGVudmlyb25tZW50YWwgc2V0dGluZ3MuCgpgYGB7cn0KcHJpbnQoUi52ZXJzaW9uKQpgYApgYGAKCgoKIyMgT3ZlcnZpZXcgb2Ygc2VudGVuY2UgbGVuZ3RoIGRpc3RyaWJ1dGlvbiBieSBkaWZmZXJlbnQgdHlwZXMgb2Ygc3BlZWNoZXMuIAoKIyMjIE5vbWluYXRpb24gc3BlZWNoZXMgCgpGaXJzdCwgd2UgbG9vayBhdCAqbm9taW5hdGlvbiBhY2NlcHRhbmNlIHNwZWVjaGVzKiBhdCBtYWpvciBwYXJ0eSdzIG5hdGlvbmFsIGNvbnZlbnRpb25zLiBGb3IgcmVsZXZhbnQgdG8gVHJ1bXAncyBzcGVlY2hlcywgd2UgbGltaXQgb3VyIGF0dGVudGlvbiB0byBzcGVlY2hlcyBmb3IgdGhlIGZpcnN0IHRlcm1zIG9mIGZvcm1lciBVLlMuIHByZXNpZGVudHMuICBXZSBub3RpY2VkIHRoYXQgYSBudW1iZXIgb2YgcHJlc2lkZW50cyBoYXZlIHZlcnkgc2hvcnQgc2VudGVuY2VzIGluIHRoZWlyIG5vbWluYXRpb24gYWNjZXB0YW5jZSBzcGVlY2hlcy4gCgojIyMjIEZpcnN0IHRlcm0KCmBgYHtyLCBmaWcud2lkdGggPSA2LCBmaWcuaGVpZ2h0ID0gNn0KCnBhcihtYXI9Yyg0LCAxMSwgMiwgMikpCgojc2VsLmNvbXBhcmlzb249bGV2ZWxzKHNlbnRlbmNlLmxpc3QkRmlsZU9yZGVyZWQpCnNlbnRlbmNlLmxpc3Quc2VsPWZpbHRlcihzZW50ZW5jZS5saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgRmlsZSA9PSAiRG9uYWxkSlRydW1wIikKc2VudGVuY2UubGlzdC5zZWwkdHlwZT1mYWN0b3Ioc2VudGVuY2UubGlzdC5zZWwkdHlwZSkKCnNlbnRlbmNlLmxpc3Quc2VsJHR5cGVPcmRlcmVkPXJlb3JkZXIoc2VudGVuY2UubGlzdC5zZWwkdHlwZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW50ZW5jZS5saXN0LnNlbCR3b3JkLmNvdW50LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXI9VCkKCmJlZXN3YXJtKHdvcmQuY291bnR+dHlwZU9yZGVyZWQsIAogICAgICAgICBkYXRhPXNlbnRlbmNlLmxpc3Quc2VsLAogICAgICAgICBob3Jpem9udGFsID0gVFJVRSwgCiAgICAgICAgIHBjaD0xNiwgY29sPWFscGhhKGJyZXdlci5wYWwoOSwgIlNldDEiKSwgMC42KSwgCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LAogICAgICAgICBzcGFjaW5nPTAuNS9ubGV2ZWxzKHNlbnRlbmNlLmxpc3Quc2VsJHR5cGVPcmRlcmVkKSwKICAgICAgICAgbGFzPTIsIHhsYWI9Ik51bWJlciBvZiB3b3JkcyBpbiBhIHNlbnRlbmNlLiIsIHlsYWI9IiIsCiAgICAgICAgIG1haW49IkRpZmZlcmVudCBzcGVlY2hlcyBvZiBEb25hbGRKVHJ1bXAiKQoKc2VudGVuY2UubGlzdCU+JQogIGZpbHRlcihGaWxlPT0iRG9uYWxkSlRydW1wIiwgCiAgICAgICAgIHR5cGU9PSJub21pbiIsIAogICAgICAgICB3b3JkLmNvdW50PD0zKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpJT4lc2FtcGxlX24oMTApCgpzZW50ZW5jZS5saXN0JT4lCiAgZmlsdGVyKEZpbGU9PSJEb25hbGRKVHJ1bXAiLCAKICAgICAgICAgdHlwZT09ImluYXVnIiwgCiAgICAgICAgIHdvcmQuY291bnQ8PTMpJT4lCiAgc2VsZWN0KHNlbnRlbmNlcyklPiVzYW1wbGVfbig1KQoKc2VudGVuY2UubGlzdCU+JQogIGZpbHRlcihGaWxlPT0iRG9uYWxkSlRydW1wIiwgCiAgICAgICAgIHR5cGU9PSJzcGVlY2hlcyIsIAogICAgICAgICB3b3JkLmNvdW50PD0zKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpJT4lc2FtcGxlX24oMTApCgpgYGAKCiMjIyMgU2Vjb25kIHRlcm0KCmBgYHtyfQoKY291bnRfdGVybSA8LSB0YWJsZShzcGVlY2gubGlzdFtzcGVlY2gubGlzdCR0eXBlID09ICJpbmF1ZyIsXSRGaWxlKQptdWx0aS50ZXJtLnNlbCA8LSBuYW1lcyh3aGljaChjb3VudF90ZXJtID4gMSkpCgoKZm9yKGkgaW4gMTpsZW5ndGgobXVsdGkudGVybS5zZWwpKXsKCiAgCiAgcG5nKHBhc3RlKCIuLi9vdXRwdXQvIiwgbXVsdGkudGVybS5zZWxbaV0sICJjb21wYXJlMTIucG5nIiwgc2VwPSIiKSwKICAgICAgd2lkdGg9MzAwLCBoZWlnaHQ9MzAwKQoKI3NlbC5jb21wYXJpc29uPWxldmVscyhzZW50ZW5jZS5saXN0JEZpbGVPcmRlcmVkKQpzZW50ZW5jZS5saXN0LnNlbD1maWx0ZXIoc2VudGVuY2UubGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9PSJpbmF1ZyIsIEZpbGUlaW4lbXVsdGkudGVybS5zZWxbaV0pCnNlbnRlbmNlLmxpc3Quc2VsJFRlcm09ZmFjdG9yKHNlbnRlbmNlLmxpc3Quc2VsJFRlcm0pCgpzZW50ZW5jZS5saXN0LnNlbCR0ZXJtT3JkZXJlZD1yZW9yZGVyKHNlbnRlbmNlLmxpc3Quc2VsJFRlcm0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VudGVuY2UubGlzdC5zZWwkd29yZC5jb3VudCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyPVQpCgpiZWVzd2FybSh3b3JkLmNvdW50fnRlcm1PcmRlcmVkLCAKICAgICAgICAgZGF0YT1zZW50ZW5jZS5saXN0LnNlbCwKICAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsIAogICAgICAgICBwY2g9MTYsIGNvbD1hbHBoYShicmV3ZXIucGFsKDksICJTZXQxIiksIDAuNiksIAogICAgICAgICBjZXg9MC41NSwgY2V4LmF4aXM9MC44LCBjZXgubGFiPTAuOCwKICAgICAgICAgc3BhY2luZz0zL25sZXZlbHMoc2VudGVuY2UubGlzdC5zZWwkdGVybU9yZGVyZWQpLAogICAgICAgICBsYXM9MiwgeGxhYj0iTnVtYmVyIG9mIHdvcmRzIGluIGEgc2VudGVuY2UuIiwgeWxhYj0iIiwKICAgICAgICAgbWFpbj0iSW5hdWd1cmF0aW9uIHNwZWVjaGVzIG9mIG11bHRpLXRlcm0iKQogIGRldi5vZmYoKQogIAogIH0KYGBgCgpXaGF0IGFyZSB0aGVzZSBzaG9ydCBzZW50ZW5jZXM/CmBgYHtyfQpzZW50ZW5jZS5saXN0JT4lCiAgZmlsdGVyKEZpbGU9PSJEb25hbGRKVHJ1bXAiLCAKICAgICAgICAgdHlwZT09Im5vbWluIiwgCiAgICAgICAgIHdvcmQuY291bnQ8PTMpJT4lCiAgc2VsZWN0KHNlbnRlbmNlcyklPiVzYW1wbGVfbigxMCkKCgpzZW50ZW5jZS5saXN0JT4lCiAgZmlsdGVyKEZpbGU9PSJBbGJlcnRHb3JlLEpyIiwgCiAgICAgICAgIHR5cGU9PSJub21pbiIsIAogICAgICAgICB3b3JkLmNvdW50PD0zKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpJT4lc2FtcGxlX24oMTApCgpzZW50ZW5jZS5saXN0JT4lCiAgZmlsdGVyKEZpbGU9PSJDbGludG9uIiwgCiAgICAgICAgIHR5cGU9PSJub21pbiIsIAogICAgICAgICB3b3JkLmNvdW50PD0zKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpCgpzZW50ZW5jZS5saXN0JT4lCiAgZmlsdGVyKEZpbGU9PSJXaWxsaWFtSkNsaW50b24iLCAKICAgICAgICAgdHlwZT09Im5vbWluIiwgVGVybT09MSwKICAgICAgICAgd29yZC5jb3VudDw9MyklPiUKICBzZWxlY3Qoc2VudGVuY2VzKQpgYGAKCgojIyMgSW5hdWd1cmFsIHNwZWVjaGVzCgpXZSBub3RpY2UgdGhhdCB0aGUgc2VudGVuY2VzIGluIGluYXVndXJhbCBzcGVlY2hlcyBhcmUgbG9uZ2VyIHRoYW4gdGhvc2UgaW4gbm9taW5hdGlvbiBhY2NlcHRhbmNlIHNwZWVjaGVzLiAKCmBgYHtyLCBmaWcud2lkdGggPSA4LCBmaWcuaGVpZ2h0ID0gN30Kc2VudGVuY2UubGlzdC5zZWw9c2VudGVuY2UubGlzdCU+JWZpbHRlcih0eXBlPT0iaW5hdWciLCBGaWxlJWluJXNlbC5jb21wYXJpc29uLCBUZXJtPT0xKQpzZW50ZW5jZS5saXN0LnNlbCRGaWxlPWZhY3RvcihzZW50ZW5jZS5saXN0LnNlbCRGaWxlKQoKc2VudGVuY2UubGlzdC5zZWwkRmlsZU9yZGVyZWQ9cmVvcmRlcihzZW50ZW5jZS5saXN0LnNlbCRGaWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlLmxpc3Quc2VsJHdvcmQuY291bnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcj1UKQpwYXIobWFyPWMoNCwgMTEsIDIsIDIpKQoKYmVlc3dhcm0od29yZC5jb3VudH5GaWxlT3JkZXJlZCwgCiAgICAgICAgIGRhdGE9c2VudGVuY2UubGlzdC5zZWwsCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLAogICAgICAgICBwY2g9MTYsIGNvbD1hbHBoYShicmV3ZXIucGFsKDksICJTZXQxIiksIDAuNiksIAogICAgICAgICBjZXg9MC41NSwgY2V4LmF4aXM9MC44LCBjZXgubGFiPTAuOCwKICAgICAgICAgc3BhY2luZz01L25sZXZlbHMoc2VudGVuY2UubGlzdC5zZWwkRmlsZU9yZGVyZWQpLAogICAgICAgICBsYXM9MiwgeWxhYj0iIiwgeGxhYj0iTnVtYmVyIG9mIHdvcmRzIGluIGEgc2VudGVuY2UuIiwKICAgICAgICAgbWFpbj0iSW5hdWd1cmFsIFNwZWVjaGVzIikKYGBgCgpTaG9ydCBzZW50ZW5jZXMgaW4gaW5hdWd1cmFsIHNwZWVjaGVzLiAKYGBge3J9CnNlbnRlbmNlLmxpc3QlPiUKICBmaWx0ZXIoRmlsZT09IkJhcmFja09iYW1hIiwgCiAgICAgICAgIHR5cGU9PSJpbmF1ZyIsIAogICAgICAgICB3b3JkLmNvdW50PD0zKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpCmBgYAoKCgpgYGB7cn0KdHJ1bXBfYmlncmFtcyA8LSBzcGVlY2gubGlzdFtzcGVlY2gubGlzdCRGaWxlID09ICJEb25hbGRKVHJ1bXAiLF0gJT4lCiAgdW5uZXN0X3Rva2VucyhiaWdyYW0sIGZ1bGx0ZXh0LCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikKCmJpZ3JhbXNfc2VwYXJhdGVkIDwtIHRydW1wX2JpZ3JhbXMgJT4lCiAgc2VwYXJhdGUoYmlncmFtLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpCgpiaWdyYW1zX2ZpbHRlcmVkIDwtIGJpZ3JhbXNfc2VwYXJhdGVkICU+JQogIGZpbHRlcighd29yZDEgJWluJSBzdG9wX3dvcmRzJHdvcmQpICU+JQogIGZpbHRlcighd29yZDIgJWluJSBzdG9wX3dvcmRzJHdvcmQpCgpiaWdyYW1fY291bnRzIDwtIGJpZ3JhbXNfZmlsdGVyZWQgJT4lIAogIGNvdW50KHdvcmQxLCB3b3JkMiwgc29ydCA9IFRSVUUpCgpiaWdyYW1zX3VuaXRlZCA8LSBiaWdyYW1zX2ZpbHRlcmVkICU+JQogIHVuaXRlKGJpZ3JhbSwgd29yZDEsIHdvcmQyLCBzZXAgPSAiICIpCgoKYmlncmFtc191bml0ZWQgPC0gYmlncmFtc191bml0ZWQgJT4lCiAgY291bnQodHlwZSwgYmlncmFtKSAlPiUKICBhcnJhbmdlKGRlc2MobikpIAoKYmlncmFtc191bml0ZWQgPC0gYmlncmFtc191bml0ZWQgJT4lIAogIG11dGF0ZShiaWdyYW0gPSBmYWN0b3IoYmlncmFtLCBsZXZlbHMgPSByZXYodW5pcXVlKGJpZ3JhbSkpKSkgJT4lCiAgZ3JvdXBfYnkodHlwZSkgJT4lIAogIGFycmFuZ2UoZGVzYyhuKSklPiUKICB0b3Bfbig1KSAlPiUgCiAgdW5ncm91cAoKCmdncGxvdChiaWdyYW1zX3VuaXRlZCwgYWVzKGJpZ3JhbSwgbiwgZmlsbCA9IHR5cGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gImNvdW50IG9mIHdvcmRzIikgKwogIGZhY2V0X3dyYXAofnR5cGUsIG5jb2wgPSAyLCBzY2FsZXMgPSAiZnJlZSIpICsKICBjb29yZF9mbGlwKCkKIyMjIyMjIyMjIyMjIyMjIyMjCgpgYGAKCgoKCgojIFN0ZXAgNTogRGF0YSBhbmFseXNpcyAtLS0gc2VudGltZW50IGFuYWxzaXMKCiMjIFNlbnRlbmNlIGxlbmd0aCB2YXJpYXRpb24gb3ZlciB0aGUgY291cnNlIG9mIHRoZSBzcGVlY2gsIHdpdGggZW1vdGlvbnMuIAoKSG93IG91ciBwcmVzaWRlbnRzIChvciBjYW5kaWRhdGVzKSBhbHRlcm5hdGUgYmV0d2VlbiBsb25nIGFuZCBzaG9ydCBzZW50ZW5jZXMgYW5kIGhvdyB0aGV5IHNoaWZ0IGJldHdlZW4gZGlmZmVyZW50IHNlbnRpbWVudHMgaW4gdGhlaXIgc3BlZWNoZXMuIEl0IGlzIGludGVyZXN0aW5nIHRvIG5vdGUgdGhhdCBzb21lIHByZXNpZGVudGlhbCBjYW5kaWRhdGVzJyBzcGVlY2ggYXJlIG1vcmUgY29sb3JmdWwgdGhhbiBvdGhlcnMuIEhlcmUgd2UgdXNlZCB0aGUgc2FtZSBjb2xvciB0aGVtZSBhcyBpbiB0aGUgbW92aWUgIkluc2lkZSBPdXQuIgoKIVtpbWFnZV0oaHR0cDovL3d3dy5zdGFmZm9yZHNjaG9vbHMubmV0L2Ntcy9saWIwMTEvVkEwMTgxODcyMy9DZW50cmljaXR5L0RvbWFpbi8zNTc0L2NoYXJhY3Rlcl9pY29uLnBuZykKCmBgYHtyLCBmaWcuaGVpZ2h0PTIuNSwgZmlnLndpZHRoPTJ9CnBhcihtZnJvdz1jKDQsMSksIG1hcj1jKDEsMCwyLDApLCBidHk9Im4iLCB4YXh0PSJuIiwgeWF4dD0ibiIsIGZvbnQubWFpbj0xKQoKZi5wbG90c2VudC5sZW4oSW4ubGlzdD1zZW50ZW5jZS5saXN0LCBJbkZpbGU9IkhpbGxhcnlDbGludG9uIiwgCiAgICAgICAgICAgICAgIEluVHlwZT0ibm9taW4iLCBJblRlcm09MSwgUHJlc2lkZW50PSJIaWxsYXJ5IENsaW50b24iKQoKZi5wbG90c2VudC5sZW4oSW4ubGlzdD1zZW50ZW5jZS5saXN0LCBJbkZpbGU9IkRvbmFsZEpUcnVtcCIsIAogICAgICAgICAgICAgICBJblR5cGU9Im5vbWluIiwgSW5UZXJtPTEsIFByZXNpZGVudD0iRG9uYWxkIFRydW1wIikKCmYucGxvdHNlbnQubGVuKEluLmxpc3Q9c2VudGVuY2UubGlzdCwgSW5GaWxlPSJCYXJhY2tPYmFtYSIsIAogICAgICAgICAgICAgICBJblR5cGU9Im5vbWluIiwgSW5UZXJtPTEsIFByZXNpZGVudD0iQmFyYWNrIE9iYW1hIikKCmYucGxvdHNlbnQubGVuKEluLmxpc3Q9c2VudGVuY2UubGlzdCwgSW5GaWxlPSJHZW9yZ2VXQnVzaCIsIAogICAgICAgICAgICAgICBJblR5cGU9Im5vbWluIiwgSW5UZXJtPTEsIFByZXNpZGVudD0iR2VvcmdlIFcuIEJ1c2giKQpgYGAKCiMjIyBXaGF0IGFyZSB0aGUgZW1vdGlvbmFsbHkgY2hhcmdlZCBzZW50ZW5jZXM/CgpgYGB7cn0KcHJpbnQoIkhpbGxhcnkgQ2xpbnRvbiIpCnNwZWVjaC5kZj10YmxfZGYoc2VudGVuY2UubGlzdCklPiUKICBmaWx0ZXIoRmlsZT09IkhpbGxhcnlDbGludG9uIiwgdHlwZT09Im5vbWluIiwgd29yZC5jb3VudD49NCklPiUKICBzZWxlY3Qoc2VudGVuY2VzLCBhbmdlcjp0cnVzdCkKc3BlZWNoLmRmPWFzLmRhdGEuZnJhbWUoc3BlZWNoLmRmKQphcy5jaGFyYWN0ZXIoc3BlZWNoLmRmJHNlbnRlbmNlc1thcHBseShzcGVlY2guZGZbLC0xXSwgMiwgd2hpY2gubWF4KV0pCgpwcmludCgiQmFyYWNrIE9iYW1hIikKc3BlZWNoLmRmPXRibF9kZihzZW50ZW5jZS5saXN0KSU+JQogIGZpbHRlcihGaWxlPT0iQmFyYWNrT2JhbWEiLCB0eXBlPT0ibm9taW4iLCBUZXJtPT0xLCB3b3JkLmNvdW50Pj01KSU+JQogIHNlbGVjdChzZW50ZW5jZXMsIGFuZ2VyOnRydXN0KQpzcGVlY2guZGY9YXMuZGF0YS5mcmFtZShzcGVlY2guZGYpCmFzLmNoYXJhY3RlcihzcGVlY2guZGYkc2VudGVuY2VzW2FwcGx5KHNwZWVjaC5kZlssLTFdLCAyLCB3aGljaC5tYXgpXSkKCnByaW50KCJHZW9yZ2UgVyBCdXNoIikKc3BlZWNoLmRmPXRibF9kZihzZW50ZW5jZS5saXN0KSU+JQogIGZpbHRlcihGaWxlPT0iR2VvcmdlV0J1c2giLCB0eXBlPT0ibm9taW4iLCBUZXJtPT0xLCB3b3JkLmNvdW50Pj00KSU+JQogIHNlbGVjdChzZW50ZW5jZXMsIGFuZ2VyOnRydXN0KQpzcGVlY2guZGY9YXMuZGF0YS5mcmFtZShzcGVlY2guZGYpCmFzLmNoYXJhY3RlcihzcGVlY2guZGYkc2VudGVuY2VzW2FwcGx5KHNwZWVjaC5kZlssLTFdLCAyLCB3aGljaC5tYXgpXSkKCnByaW50KCJEb25hbGQgVHJ1bXAiKQpzcGVlY2guZGY9dGJsX2RmKHNlbnRlbmNlLmxpc3QpJT4lCiAgZmlsdGVyKEZpbGU9PSJEb25hbGRKVHJ1bXAiLCB0eXBlPT0ibm9taW4iLCBUZXJtPT0xLCB3b3JkLmNvdW50Pj01KSU+JQogIHNlbGVjdChzZW50ZW5jZXMsIGFuZ2VyOnRydXN0KQpzcGVlY2guZGY9YXMuZGF0YS5mcmFtZShzcGVlY2guZGYpCmFzLmNoYXJhY3RlcihzcGVlY2guZGYkc2VudGVuY2VzW2FwcGx5KHNwZWVjaC5kZlssLTFdLCAyLCB3aGljaC5tYXgpXSkKCmBgYAoKCiMjIENsdXN0ZXJpbmcgb2YgZW1vdGlvbnMKYGBge3IsIGZpZy53aWR0aD0yLCBmaWcuaGVpZ2h0PTJ9CmhlYXRtYXAuMihjb3Ioc2VudGVuY2UubGlzdCU+JWZpbHRlcih0eXBlPT0iaW5hdWciKSU+JXNlbGVjdChhbmdlcjp0cnVzdCkpLCAKICAgICAgICAgIHNjYWxlID0gIm5vbmUiLCAKICAgICAgICAgIGNvbCA9IGJsdWVyZWQoMTAwKSwgLCBtYXJnaW49Yyg2LCA2KSwga2V5PUYsCiAgICAgICAgICB0cmFjZSA9ICJub25lIiwgZGVuc2l0eS5pbmZvID0gIm5vbmUiKQoKcGFyKG1hcj1jKDQsIDYsIDIsIDEpKQplbW8ubWVhbnM9Y29sTWVhbnMoc2VsZWN0KHNlbnRlbmNlLmxpc3QsIGFuZ2VyOnRydXN0KT4wLjAxKQpjb2wudXNlPWMoInJlZDIiLCAiZGFya2dvbGRlbnJvZDEiLCAKICAgICAgICAgICAgImNoYXJ0cmV1c2UzIiwgImJsdWV2aW9sZXQiLAogICAgICAgICAgICAiZGFya2dvbGRlbnJvZDIiLCAiZG9kZ2VyYmx1ZTMiLCAKICAgICAgICAgICAgImRhcmtnb2xkZW5yb2QxIiwgImRhcmtnb2xkZW5yb2QxIikKYmFycGxvdChlbW8ubWVhbnNbb3JkZXIoZW1vLm1lYW5zKV0sIGxhcz0yLCBjb2w9Y29sLnVzZVtvcmRlcihlbW8ubWVhbnMpXSwgaG9yaXo9VCwgbWFpbj0iSW5hdWd1cmFsIFNwZWVjaGVzIikKYGBgCgoKCg==